import store from '@/store';
import { refreshAccessToken } from '@/utils/token';
import { resetLogin } from '@/utils/index';

const websocketUrl = process.env.VUE_APP_WEBSOCKET_URL;

let socket = null;
let lockReconnect = false;
let reconnectTimer = null;
let globalCallback = () => {};
let statusChangeCallback = null;
let isInitializing = false;
let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 5;

/* ===== 心跳 ===== */
const heartCheck = {
    timeout: 5000,
    timer: null,
    serverTimer: null,
    reset() {
        clearTimeout(this.timer);
        clearTimeout(this.serverTimer);
        return this;
    },
    start(onTimeout = () => {}) {
        this.reset();
        this.timer = setTimeout(() => {
            if (socket && socket.readyState === WebSocket.OPEN) {
                socket.send(JSON.stringify({ command: 'HEARTBEAT' }));
                this.serverTimer = setTimeout(() => onTimeout(), this.timeout);
            }
        }, this.timeout);
    }
};

/* ===== 对内：真正创建连接 ===== */
let closedByTokenExpired = false;

async function waitIfRefreshing() {
    if (!store.state.isRefreshing) return;
    console.log('[waitIfRefreshing] 等待isRefreshing=false...');
    await Promise.race([
        new Promise(resolve => {
            const unwatch = store.watch(state => state.isRefreshing, val => {
                if (!val) {
                    unwatch();
                    resolve();
                }
            });
        }),
        new Promise(resolve => setTimeout(resolve, 10000)) // 10 s 超时
    ]);
}

async function initSocketInner() {
    if (isInitializing) return Promise.resolve();
    isInitializing = true;
    closeSocket();

    await waitIfRefreshing();

    const { access_token } = store.state.userToken;
    console.log('[initSocketInner] 建连时拿到的token:', access_token);
    if (!access_token) {
        isInitializing = false;
        return Promise.reject('NO_TOKEN');
    }

    return new Promise((resolve, reject) => {
        try {
            socket = new WebSocket(websocketUrl, [access_token]);
        } catch (e) {
            isInitializing = false;
            reject(e);
            return;
        }

        socket.onopen = () => {
            reconnectAttempts = 0;
            heartCheck.reset().start(() => socket.close());
            triggerStatusChange('connected');
            resolve();
        };

        socket.onmessage = e => {
            const data = JSON.parse(e.data);
            if (data.subMsgType === 'access_token_expired') {
                console.log('[WebSocket] 收到token过期消息');
                closedByTokenExpired = true;
                socket.close();
                return;
            }
            if (data.command !== 'HEARTBEAT') globalCallback(data);
            heartCheck.reset().start(() => socket.close());
        };

        socket.onerror = () => triggerStatusChange('error');

        socket.onclose = () => {
            heartCheck.reset();
            triggerStatusChange('disconnected');
            if (closedByTokenExpired) {
                closedByTokenExpired = false;
                handleTokenExpiredAndReconnect();
            } else {
                scheduleReconnect();
            }
        };

        const unload = () => socket.close();
        window.addEventListener('beforeunload', unload, { once: true });
        isInitializing = false;
    });
}

/* ===== 刷新 token 然后再连 ===== */
async function handleTokenExpiredAndReconnect() {
    if (lockReconnect) return;
    console.log('[handleTokenExpiredAndReconnect] 开始刷新token');
    lockReconnect = true;
    try {
        const { accessToken } = await refreshAccessToken();
        console.log('[handleTokenExpiredAndReconnect] 刷新结果:', accessToken);
        if (!accessToken) throw new Error('刷新后仍无token');
        reconnectAttempts = 0;
        await initSocketInner();
    } catch (e) {
        console.error('Token 刷新失败，放弃重连', e);
        resetLogin();
    } finally {
        console.log('[handleTokenExpiredAndReconnect] lockReconnect已释放');
        lockReconnect = false;
    }
}

/* ===== 对外：唯一入口 ===== */
function initSocket(callback) {
    if (typeof callback === 'function') globalCallback = callback;
    initSocketInner().catch(() => {});
}

/* ===== 重连 ===== */
function scheduleReconnect() {
    if (lockReconnect || isInitializing) return;
    if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
        console.warn('WebSocket 已达最大重连次数');
        return;
    }
    lockReconnect = true;
    const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 10000);
    reconnectAttempts++;
    reconnectTimer = setTimeout(() => {
        lockReconnect = false;
        initSocket(globalCallback);
    }, delay);
}

/* ===== 工具函数 ===== */
function closeSocket() {
    if (socket) {
        socket.onopen = socket.onmessage = socket.onerror = socket.onclose = null;
        socket.close();
        socket = null;
    }
}

function send(msg) {
    if (socket && socket.readyState === WebSocket.OPEN) {
        socket.send(JSON.stringify(msg));
    } else {
        console.warn('WebSocket 未连接，发送失败');
    }
}

function safeSend(data, retry = 0, max = 5, delay = 1000) {
    if (!isConnected()) {
        if (retry < max) {
            setTimeout(() => safeSend(data, retry + 1, max, delay), delay);
        } else console.warn('safeSend：连接超时');
        return;
    }
    send(data);
}

function isConnected() {
    return socket && socket.readyState === WebSocket.OPEN;
}

function isConnecting() {
    return socket && socket.readyState === WebSocket.CONNECTING;
}

function onStatusChange(cb) {
    statusChangeCallback = cb;
}

function triggerStatusChange(status) {
    statusChangeCallback?.(status);
}

export default {
    initSocket,
    closeSocket,
    sendSocket: safeSend,
    isConnected,
    isConnecting,
    onStatusChange
};
